package com.avcompris.util;

import static com.avcompris.util.ExceptionUtils.nonNullArgument;
import static java.lang.Thread.currentThread;
import static org.apache.commons.io.FileUtils.openInputStream;
import static org.apache.commons.io.FileUtils.openOutputStream;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Properties;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import com.avcompris.common.annotation.Nullable;

/**
 * utilities for XSL Transformations.
 * 
 * @author David Andriana Copyright Avantage Compris SARL 2008-2009 ©
 */
public class TransformUtils extends AbstractUtils {

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param xsltReader
	 *            the {@link Reader} to the XSLT stylesheet
	 * @param xmlReader
	 *            the {@link Reader} to the XML content
	 * @return the transformed content
	 */
	public static String transformToString(final Reader xsltReader,
			final Reader xmlReader) throws TransformerException {

		return transformToString(xsltReader, null, xmlReader);
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param xsltReader
	 *            the {@link Reader} to the XSLT stylesheet
	 * @param params
	 *            the XSLT params to pass
	 * @param xmlReader
	 *            the {@link Reader} to the XML content
	 * @return the transformed content
	 */
	public static String transformToString(final Reader xsltReader,
			@Nullable final Properties params, final Reader xmlReader)
			throws TransformerException {

		nonNullArgument(xsltReader, "xsltReader");
		nonNullArgument(xmlReader, "xmlReader");

		return transformToString(new StreamSource(xsltReader), params,
				new StreamSource(xmlReader));
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param xsltReader
	 *            the {@link Reader} to the XSLT stylesheet
	 * @param xmlReader
	 *            the {@link Reader} to the XML content
	 * @param result
	 *            the {@link Result} placeholder
	 */
	public static void transform(final Reader xsltReader,
			final Reader xmlReader, final Result result)
			throws TransformerException {

		transform(xsltReader, null, xmlReader, result);
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param xsltReader
	 *            the {@link Reader} to the XSLT stylesheet
	 * @param xml
	 *            the XML content
	 * @return the result
	 */
	public static String transformToString(final Reader xsltReader,
			final String xml) throws TransformerException, IOException {

		return transformToString(xsltReader, null, xml);
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param xsltReader
	 *            the {@link Reader} to the XSLT stylesheet
	 * @param params
	 *            the XSLT params to pass
	 * @param xml
	 *            the XML content
	 * @return the result
	 */
	public static String transformToString(final Reader xsltReader,
			@Nullable final Properties params, final String xml)
			throws TransformerException, IOException {

		nonNullArgument(xml, "xml");

		final Writer writer = new StringWriter();
		try {

			final Result result = new StreamResult(writer);

			transform(xsltReader, params, new StringReader(xml), result);

		} finally {
			writer.close();
		}

		return writer.toString();
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param xsltReader
	 *            the {@link Reader} to the XSLT stylesheet
	 * @param params
	 *            the XSLT params to pass
	 * @param xmlReader
	 *            the {@link Reader} to the XML content
	 * @param result
	 *            the {@link Result} placeholder
	 */
	public static void transform(final Reader xsltReader,
			@Nullable final Properties params, final Reader xmlReader,
			final Result result) throws TransformerException {

		nonNullArgument(xsltReader, "xsltReader");
		nonNullArgument(xmlReader, "xmlReader");

		transform(new StreamSource(xsltReader), params, new StreamSource(
				xmlReader), result);
	}

	/**
	 * transform a XML content via a XSLT stylesheet. This method doesn't close
	 * the given {@link InputStream}.
	 * 
	 * @param xsltIs
	 *            the {@link InputStream} reading the XSLT stylesheet
	 * @param xmlReader
	 *            the {@link Reader} to the XML content
	 * @param result
	 *            the {@link Result} placeholder
	 */
	public static void transform(final InputStream xsltIs,
			final Reader xmlReader, final Result result)
			throws TransformerException {

		transform(xsltIs, null, xmlReader, result);
	}

	/**
	 * transform a XML content via a XSLT stylesheet. This method doesn't close
	 * the given {@link InputStream}.
	 * 
	 * @param xsltIs
	 *            the {@link InputStream} reading the XSLT stylesheet
	 * @param xmlReader
	 *            the {@link Reader} to the XML content
	 * @return the transformerd content
	 */
	public static String transformToString(final InputStream xsltIs,
			final Reader xmlReader) throws TransformerException {

		return transformToString(xsltIs, null, xmlReader);
	}

	/**
	 * @param args
	 *            the key/value pairs to pass as XSLT params
	 */
	public static String transformToString(final InputStream xsltIs,
			final Reader xmlReader, @Nullable final String... args)
			throws TransformerException {

		return transformToString(xsltIs, loadArgsIntoProperties(args),
				xmlReader);
	}

	/**
	 * transform a XML content via a XSLT stylesheet. This method doesn't close
	 * the given {@link InputStream}.
	 * 
	 * @param xsltIs
	 *            the {@link InputStream} reading the XSLT stylesheet
	 * @param params
	 *            the XSLT params to pass
	 * @param xmlReader
	 *            the {@link Reader} to the XML content
	 * @return the transformerd content
	 */
	public static String transformToString(final InputStream xsltIs,
			@Nullable final Properties params, final Reader xmlReader)
			throws TransformerException {

		nonNullArgument(xsltIs, "xsltIs");
		nonNullArgument(xmlReader, "xmlReader");

		return transformToString(new StreamSource(xsltIs), params,
				new StreamSource(xmlReader));
	}

	/**
	 * transform a XML content via a XSLT stylesheet. This method doesn't close
	 * the given {@link InputStream}.
	 * 
	 * @param xsltIs
	 *            the {@link InputStream} reading the XSLT stylesheet
	 * @param params
	 *            the XSLT params to pass
	 * @param reader
	 *            the {@link Reader} to the XML content
	 * @param result
	 *            the {@link Result} placeholder
	 */
	public static void transform(final InputStream xsltIs,
			@Nullable final Properties params, final Reader reader,
			final Result result) throws TransformerException {

		nonNullArgument(xsltIs, "xsltIs");
		nonNullArgument(reader, "reader");

		transform(new StreamSource(xsltIs), params, new StreamSource(reader),
				result);
	}

	/**
	 * transform a XML content via a XSLT stylesheet. This method doesn't close
	 * the given {@link InputStream}.
	 * 
	 * @param xsltSource
	 *            the XSLT stylesheet
	 * @param xmlSource
	 *            the XML content
	 * @param result
	 *            the {@link Result} placeholder
	 */
	public static void transform(final Source xsltSource,
			final Source xmlSource, final Result result)
			throws TransformerException {

		transform(xsltSource, null, xmlSource, result);
	}

	/**
	 * transform a XML content via a XSLT stylesheet. This method doesn't close
	 * the given {@link InputStream}.
	 * 
	 * @param xsltSource
	 *            the XSLT stylesheet
	 * @param params
	 *            the XSLT params to pass
	 * @param xmlSource
	 *            the XML content
	 * @param result
	 *            the {@link Result} placeholder
	 */
	public static void transform(final Source xsltSource,
			@Nullable final Properties params, final Source xmlSource,
			final Result result) throws TransformerException {

		final ClassLoader classLoader = currentThread().getContextClassLoader();

		transform(xsltSource, new XsltResourceURIResolver(classLoader), params,
				xmlSource, result);
	}

	/**
	 * transform a XML content via a XSLT stylesheet. This method doesn't close
	 * the given {@link InputStream}.
	 * 
	 * @param xsltSource
	 *            the XSLT stylesheet
	 * @param uriResolver
	 *            the URI resolver to use
	 * @param params
	 *            the XSLT params to pass
	 * @param xmlSource
	 *            the XML content
	 * @param result
	 *            the {@link Result} placeholder
	 */
	public static void transform(final Source xsltSource,
			@Nullable final URIResolver uriResolver,
			@Nullable final Properties params, final Source xmlSource,
			final Result result) throws TransformerException {

		nonNullArgument(xsltSource, "xsltSource");
		nonNullArgument(xmlSource, "xmlSource");
		nonNullArgument(result, "result");

		final TransformerFactory txFactory = TransformerFactory.newInstance();

		if (uriResolver != null) {

			txFactory.setURIResolver(uriResolver);
		}

		final Transformer t = txFactory.newTransformer(xsltSource);

		if (params != null) {

			for (final Object key : params.keySet()) {

				final String name = (String) key;

				final String value = params.getProperty(name);

				t.setParameter(name, value);
			}
		}

		t.transform(xmlSource, result);
	}

	/**
	 * transform a XML content via a XSLT stylesheet. This method doesn't close
	 * the given {@link InputStream}.
	 * 
	 * @param xsltSource
	 *            the XSLT stylesheet
	 * @param params
	 *            the XSLT params to pass
	 * @param xmlSource
	 *            the XML content
	 * @return the transformed result
	 */
	public static String transformToString(final Source xsltSource,
			@Nullable final Properties params, final Source xmlSource)
			throws TransformerException {

		final Writer writer = new StringWriter();

		transform(xsltSource, params, xmlSource, new StreamResult(writer));

		return writer.toString();
	}

	/**
	 * transform a XML content via a XSLT stylesheet. This method doesn't close
	 * the given {@link InputStream}.
	 * 
	 * @param xsltSource
	 *            the XSLT stylesheet
	 * @param uriResolver
	 *            the URI resolver to use
	 * @param params
	 *            the XSLT params to pass
	 * @param xmlSource
	 *            the XML content
	 * @return the transformed result
	 */
	public static String transformToString(final Source xsltSource,
			@Nullable URIResolver uriResolver,
			@Nullable final Properties params, final Source xmlSource)
			throws TransformerException {

		final Writer writer = new StringWriter();

		transform(xsltSource, uriResolver, params, xmlSource, new StreamResult(
				writer));

		return writer.toString();
	}

	/**
	 * transform a XML content via a XSLT stylesheet. This method doesn't close
	 * the given {@link InputStream}.
	 * 
	 * @param xsltSource
	 *            the XSLT stylesheet
	 * @param xmlSource
	 *            the XML content
	 * @return the transformed result
	 */
	public static String transformToString(final Source xsltSource,
			final Source xmlSource) throws TransformerException {

		return transformToString(xsltSource, null, xmlSource);
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param xsltFile
	 *            the {@link File} of the XSLT stylesheet
	 * @param xmlFile
	 *            the {@link File} of the XML content
	 * @param resultFile
	 *            the resulting {@link File}
	 */
	public static void transform(final File xsltFile, final File xmlFile,
			final File resultFile) throws TransformerException {

		transform(xsltFile, null, xmlFile, resultFile);
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param xsltFile
	 *            the {@link File} of the XSLT stylesheet
	 * @param xmlFile
	 *            the {@link File} of the XML content
	 * @param resultFile
	 *            the resulting {@link File}
	 * @param args
	 *            the key/value pairs to pass as XSLT params
	 */
	public static void transform(final File xsltFile, final File xmlFile,
			final File resultFile, @Nullable final String... args)
			throws TransformerException {

		transform(xsltFile, loadArgsIntoProperties(args), xmlFile, resultFile);
	}

	// /**
	// * transform a XML content via a XSLT stylesheet.
	// *
	// * @param xsltFile
	// * the {@link File} of the XSLT stylesheet
	// * @param xmlFile
	// * the {@link File} of the XML content
	// * @return the transformed content
	// */
	// public static String transformToString(final File xsltFile,
	// final File xmlFile) throws TransformerException {
	//
	// return transformToString(xsltFile, null, xmlFile);
	// }

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param xsltFile
	 *            the {@link File} of the XSLT stylesheet
	 * @param xmlFile
	 *            the {@link File} of the XML content
	 * @param args
	 *            the key/value pairs to pass as XSLT params
	 * @return the transformed content
	 */
	public static String transformToString(final File xsltFile,
			final File xmlFile, @Nullable final String... args)
			throws TransformerException {

		return transformToString(xsltFile, loadArgsIntoProperties(args),
				xmlFile);
	}

	/**
	 * load key/value pairs as properties.
	 * 
	 * @param args
	 *            the key/value pairs.
	 * @return the loaded properties.
	 */
	private static @Nullable
	Properties loadArgsIntoProperties(@Nullable final String[] args) {

		if (args == null) {
			return null;
		}

		final Properties properties = new Properties();

		for (int i = 0; i < args.length; i += 2) {

			final String key = args[i];
			final String value = args[i + 1];

			properties.setProperty(key, value);
		}

		return properties;
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param xsltFile
	 *            the {@link File} of the XSLT stylesheet
	 * @param params
	 *            the XSLT params to pass
	 * @param xmlFile
	 *            the {@link File} of the XML content
	 * @return the transformed content
	 */
	public static String transformToString(final File xsltFile,
			@Nullable final Properties params, final File xmlFile)
			throws TransformerException {

		nonNullArgument(xsltFile, "xsltFile");
		nonNullArgument(xmlFile, "xmlFile");

		return transformToString(new StreamSource(xsltFile),
				new XsltFileURIResolver(xsltFile), params, new StreamSource(
						xmlFile));
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param xsltFile
	 *            the {@link File} of the XSLT stylesheet
	 * @param params
	 *            the XSLT params to pass
	 * @param reader
	 *            the reader to the XML content
	 * @return the transformed content
	 */
	public static String transformToString(final File xsltFile,
			@Nullable final Properties params, final Reader reader)
			throws TransformerException {

		nonNullArgument(xsltFile, "xsltFile");
		nonNullArgument(reader, "reader");

		return transformToString(new StreamSource(xsltFile),
				new XsltFileURIResolver(xsltFile), params, new StreamSource(
						reader));
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param xsltFile
	 *            the {@link File} of the XSLT stylesheet
	 * @param reader
	 *            the reader to the XML content
	 * @return the transformed content
	 */
	public static String transformToString(final File xsltFile,
			final Reader reader) throws TransformerException {

		return transformToString(xsltFile, null, reader);
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param xsltFile
	 *            the {@link File} of the XSLT stylesheet
	 * @param xml
	 *            the XML content
	 * @return the transformed content
	 */
	public static String transformToString(final File xsltFile, final String xml)
			throws TransformerException {

		nonNullArgument(xml, "xml");

		return transformToString(xsltFile, new StringReader(xml));
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param xsltFile
	 *            the {@link File} of the XSLT stylesheet
	 * @param params
	 *            the XSLT params to pass
	 * @param xmlFile
	 *            the {@link File} of the XML content
	 * @param resultFile
	 *            the resulting {@link File}
	 */
	public static void transform(final File xsltFile,
			@Nullable final Properties params, final File xmlFile,
			final File resultFile) throws TransformerException {

		nonNullArgument(xsltFile, "xsltFile");
		nonNullArgument(xmlFile, "xmlFile");
		nonNullArgument(resultFile, "resultFile");

		transform(new StreamSource(xsltFile),
				new XsltFileURIResolver(xsltFile), params, new StreamSource(
						xmlFile), new StreamResult(resultFile));
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param c
	 *            the class from which search for the XSLT stylesheet as a
	 *            resource
	 * @param xsltPath
	 *            the path to the XSLT stylesheet as a resource
	 * @param params
	 *            the XSLT params to pass
	 * @param xml
	 *            the XML content
	 * @param os
	 *            the output stream where to send the result
	 */
	public static void transform(final Class<?> c, final String xsltPath,
			@Nullable final Properties params, final String xml,
			final OutputStream os) throws TransformerException, IOException {

		nonNullArgument(xml, "xml");
		nonNullArgument(os, "os");

		transform(c, xsltPath, params, new StreamSource(new StringReader(xml)),
				new StreamResult(os));
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param c
	 *            the class from which search for the XSLT stylesheet as a
	 *            resource
	 * @param xsltPath
	 *            the path to the XSLT stylesheet as a resource
	 * @param params
	 *            the XSLT params to pass
	 * @param xmlIs
	 *            the input stream that reads the XML content
	 * @param os
	 *            the output stream where to send the result
	 */
	public static void transform(final Class<?> c, final String xsltPath,
			@Nullable final Properties params, final InputStream xmlIs,
			final OutputStream os) throws TransformerException, IOException {

		nonNullArgument(xmlIs, "xmlIs");
		nonNullArgument(os, "os");

		transform(c, xsltPath, params, new StreamSource(xmlIs),
				new StreamResult(os));
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param c
	 *            the class from which search for the XSLT stylesheet as a
	 *            resource
	 * @param xsltPath
	 *            the path to the XSLT stylesheet as a resource
	 * @param xmlIs
	 *            the input stream that reads the XML content
	 * @param os
	 *            the output stream where to send the result
	 */
	public static void transform(final Class<?> c, final String xsltPath,
			final InputStream xmlIs, final OutputStream os)
			throws TransformerException, IOException {

		nonNullArgument(xmlIs, "xmlIs");
		nonNullArgument(os, "os");

		transform(c, xsltPath, null, new StreamSource(xmlIs), new StreamResult(
				os));
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param c
	 *            the class from which search for the XSLT stylesheet as a
	 *            resource
	 * @param xsltPath
	 *            the path to the XSLT stylesheet as a resource
	 * @param params
	 *            the XSLT params to pass
	 * @param xml
	 *            the XML content
	 * @param result
	 *            where to store the result
	 */
	public static void transform(final Class<?> c, final String xsltPath,
			@Nullable final Properties params, final String xml,
			final Result result) throws TransformerException, IOException {

		nonNullArgument(xml, "xml");

		transform(c, xsltPath, params, new StreamSource(new StringReader(xml)),
				result);
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param c
	 *            the class from which search for the XSLT stylesheet as a
	 *            resource
	 * @param xsltPath
	 *            the path to the XSLT stylesheet as a resource
	 * @param xml
	 *            the XML content
	 * @param result
	 *            where to store the result
	 */
	public static void transform(final Class<?> c, final String xsltPath,
			final String xml, final Result result) throws TransformerException,
			IOException {

		transform(c, xsltPath, null, xml, result);
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param c
	 *            the class from which search for the XSLT stylesheet as a
	 *            resource
	 * @param xsltPath
	 *            the path to the XSLT stylesheet as a resource
	 * @param params
	 *            the XSLT params to pass
	 * @param xml
	 *            the XML content
	 * @return the transformed content
	 */
	public static String transformToString(final Class<?> c,
			final String xsltPath, @Nullable final Properties params,
			final String xml) throws TransformerException, IOException {

		nonNullArgument(xml, "xml");

		final Writer writer = new StringWriter();

		transform(c, xsltPath, params, new StreamSource(new StringReader(xml)),
				new StreamResult(writer));

		return writer.toString();
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param c
	 *            the class from which search for the XSLT stylesheet as a
	 *            resource
	 * @param xsltPath
	 *            the path to the XSLT stylesheet as a resource
	 * @param xml
	 *            the XML content
	 * @return the transformed content
	 */
	public static String transformToString(final Class<?> c,
			final String xsltPath, final String xml)
			throws TransformerException, IOException {

		return transformToString(c, xsltPath, null, xml);
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param c
	 *            the class from which search for the XSLT stylesheet as a
	 *            resource
	 * @param xsltPath
	 *            the path to the XSLT stylesheet as a resource
	 * @param xml
	 *            the XML content
	 * @param os
	 *            the output stream where to send the result
	 */
	public static void transform(final Class<?> c, final String xsltPath,
			final String xml, final OutputStream os)
			throws TransformerException, IOException {

		transform(c, xsltPath, null, xml, os);
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param c
	 *            the class from which search for the XSLT stylesheet as a
	 *            resource
	 * @param xsltPath
	 *            the path to the XSLT stylesheet as a resource
	 * @param xml
	 *            the XML content
	 * @param resultFile
	 *            the output file where to store the result
	 */
	public static void transform(final Class<?> c, final String xsltPath,
			final String xml, final File resultFile)
			throws TransformerException, IOException {

		transform(c, xsltPath, null, xml, resultFile);
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param c
	 *            the class from which search for the XSLT stylesheet as a
	 *            resource
	 * @param xsltPath
	 *            the path to the XSLT stylesheet as a resource
	 * @param params
	 *            the XSLT params to pass
	 * @param xml
	 *            the XML content
	 * @param resultFile
	 *            the output file where to store the result
	 */
	public static void transform(final Class<?> c, final String xsltPath,
			@Nullable final Properties params, final String xml,
			final File resultFile) throws TransformerException, IOException {

		nonNullArgument(c, "class");
		nonNullArgument(xsltPath, "xsltPath");
		nonNullArgument(xml, "xml");
		nonNullArgument(resultFile, "resultFile");

		final OutputStream os = openOutputStream(resultFile);
		try {

			transform(c, xsltPath, params, xml, os);

		} finally {
			os.close();
		}
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param c
	 *            the class from which search for the XSLT stylesheet as a
	 *            resource
	 * @param xsltPath
	 *            the path to the XSLT stylesheet as a resource
	 * @param params
	 *            the XSLT params to pass
	 * @param xmlFile
	 *            the input file where to find the XML content
	 * @param resultFile
	 *            the output file where to store the result
	 */
	public static void transform(final Class<?> c, final String xsltPath,
			@Nullable final Properties params, final File xmlFile,
			final File resultFile) throws TransformerException, IOException {

		nonNullArgument(c, "class");
		nonNullArgument(xsltPath, "xsltPath");
		nonNullArgument(xmlFile, "xmlFile");
		nonNullArgument(resultFile, "resultFile");

		final InputStream is = openInputStream(xmlFile);
		try {

			final OutputStream os = openOutputStream(resultFile);
			try {

				transform(c, xsltPath, params, is, os);

			} finally {
				os.close();
			}

		} finally {
			is.close();
		}
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param c
	 *            the class from which search for the XSLT stylesheet as a
	 *            resource
	 * @param xsltPath
	 *            the path to the XSLT stylesheet as a resource
	 * @param xmlFile
	 *            the input file where to find the XML content
	 * @param resultFile
	 *            the output file where to store the result
	 */
	public static void transform(final Class<?> c, final String xsltPath,
			final File xmlFile, final File resultFile)
			throws TransformerException, IOException {

		transform(c, xsltPath, null, xmlFile, resultFile);
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param c
	 *            the class from which search for the XSLT stylesheet as a
	 *            resource
	 * @param xsltPath
	 *            the path to the XSLT stylesheet as a resource
	 * @param params
	 *            the XSLT params to pass
	 * @param xmlSource
	 *            the XML content
	 * @param result
	 *            where to send the result
	 */
	public static void transform(final Class<?> c, final String xsltPath,
			@Nullable final Properties params, final Source xmlSource,
			final Result result) throws TransformerException, IOException {

		nonNullArgument(c, "class");
		nonNullArgument(xsltPath, "xsltPath");
		nonNullArgument(xmlSource, "xmlSource");
		nonNullArgument(result, "result");

		final ClassLoader classLoader = c.getClassLoader();

		final InputStream is = classLoader.getResourceAsStream(xsltPath);

		if (is == null) {
			throw new IOException("Cannot find XSLT resource: [" + xsltPath
					+ "]");
		}

		try {

			transform(new StreamSource(is), params, xmlSource, result);

		} finally {

			is.close();
		}
	}

	/**
	 * transform a XML content via a XSLT stylesheet.
	 * 
	 * @param c
	 *            the class from which search for the XSLT stylesheet as a
	 *            resource
	 * @param xsltPath
	 *            the path to the XSLT stylesheet as a resource
	 * @param xmlSource
	 *            the XML content
	 * @param result
	 *            where to send the result
	 */
	public static void transform(final Class<?> c, final String xsltPath,
			final Source xmlSource, final Result result)
			throws TransformerException, IOException {

		transform(c, xsltPath, null, xmlSource, result);
	}
}
